/*
 * pcb.h
 *
 *  Created on: May 14, 2013
 *      Author: Edward
 */

#include "process.h"
#include "queue.h"
#include "shared_memory.h"

#ifndef PCB_H_
#define PCB_H_

//Process states
#define NEW           0
#define READY         1
#define RUNNING       2
#define INTERRUPTED   3
#define BLOCKED       4
#define TERMINATED	  5
#define PROCESS_SIZE  1000


//this construction is to remove the reliance on pcb.h from mutex.h and condition_variable.h,
//thus removing a cyclical dependency
#ifndef PCB_STR_
#define PCB_STR_
typedef struct pcb_str PCBStr;
typedef PCBStr * PCBPtr;
#endif

struct pcb_str {
	int my_counter;
	int	pid;
	int next_step;		// this is the step count that the CPU had gotten to when this process was
	// prempted (like a PC register value)
	int state;			// e.g. 0=running, 1=ready, 2=interrupted, 3=blocked
	ProcessPtr proc;    // pointer to the actual process
	int waiting_on;		// which queue is it in if it is waiting on something (blocked)
	//int owns;			// which mutex lock does it own
  SharedPtr shared; //data shared with other PCB. Leave 0 if no shared data.
  char prod_cons_type;
  
	// anything else you need
    int burst_time;
    int priority;
    int time_slice;


    //queue fields
    int front;
    int back;
    int size_r;
    int size_w;
    struct pcb_str * ready_queue[PROCESS_SIZE];
    struct pcb_str * waiting_queue[PROCESS_SIZE];

	//member functions
    int(*setTimeSlice)(struct pcb_str *, int);
    int(*getTimeSlice)(struct pcb_str *);
    int(*setPriority)(struct pcb_str *, int);
    int(*getPriority)(struct pcb_str *);
    int(*setBurstTime)(struct pcb_str *, int);
    int(*getBurstTime)(struct pcb_str *);
	int(*setPID)(struct pcb_str *, int);
	int(*getPID)(struct pcb_str *);
	int(*setNextStep)(struct pcb_str *, int);
	int(*getNextStep)(struct pcb_str *);
	int(*setState)(struct pcb_str *, int);
	int(*getState)(struct pcb_str *);
	int(*setReadyQueue)(struct pcb_str *, struct pcb_str *);
	struct pcb_str * (*getReadyQueue)(struct pcb_str *);
	struct pcb_str *(*dequeueReadyQueue)(struct pcb_str *);
	struct pcb_str *(*dequeueWaitingQueue)(struct pcb_str *);
	int(*setIOQueue)(struct pcb_str *, struct pcb_str *);
	struct pcb_str * (*getIOQueue)(struct pcb_str *);
	int(*createProcess)(struct pcb_str *, int, int, int);
	//int(*ownsMutex)(struct pcb_str *, int);
	int(*toString)(struct pcb_str *);
	int(*stepProcess)(struct pcb_str *);
};


PCBPtr newPcbConstructor();

int setTimeSlice(PCBPtr this, int time_slice);
int getTimeSlice(PCBPtr this);
int setBurstTime(PCBPtr this, int burst_time);
int getBurstTime(PCBPtr this);
int setPriority(PCBPtr this, int priority);
int getPriority(PCBPtr this);
int setPID(PCBPtr this, int id);
int getPID(PCBPtr this);
int setNextStep(PCBPtr this, int nextStep);


int getNextStep(PCBPtr this);
int setState(PCBPtr this, int state);
int getState(PCBPtr this);
int setReadyQueue(PCBPtr this, PCBPtr process);
PCBPtr getReadyQueue(PCBPtr this);
int setIOQueue(PCBPtr this, PCBPtr process);
PCBPtr getIOQueue(PCBPtr this);
PCBPtr dequeueReadyQueue(PCBPtr this);
PCBPtr dequeueWaitingQueue(PCBPtr this);
int createProcess(PCBPtr this, int processID, int burst_time, int state);
//int ownsMutex(PCBPtr this, int mutex);
int toString(PCBPtr this);
int stepProcess(PCBPtr this);

#endif /* PCB_H_ */

